package com.harmontronics.hanma.paas.paas.domain.app.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.harmontronics.hanma.paas.paas.common.PageBase;
import com.harmontronics.hanma.paas.paas.consts.DbConstants;
import com.harmontronics.hanma.paas.paas.domain.app.entity.HmDatasource;
import com.harmontronics.hanma.paas.paas.domain.app.entity.HmDatasourceEnv;
import com.harmontronics.hanma.paas.paas.domain.app.entity.valueobject.Fields;
import com.harmontronics.hanma.paas.paas.domain.app.entity.valueobject.I18nKeyEnum;
import com.harmontronics.hanma.paas.paas.domain.app.repository.persistence.HmDatasourceEnvRepository;
import com.harmontronics.hanma.paas.paas.domain.app.repository.persistence.HmDatasourceRepository;
import com.harmontronics.hanma.paas.paas.domain.app.repository.po.HmDatasourceEnvPO;
import com.harmontronics.hanma.paas.paas.domain.app.repository.po.HmDatasourcePO;
import com.harmontronics.hanma.paas.paas.exception.ErrorKeyException;
import com.harmontronics.hanma.paas.paas.utils.EscapeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author ldb
 */
@Service("hmDatasourceService")
@DS("#header.App-Unique")
public class HmDatasourceService {

    @Autowired
    private HmDatasourceRepository hmDatasourceRepository;
    @Autowired
    private HmDatasourceEnvRepository hmDatasourceEnvRepository;


    public HmDatasource findById(Long id) {
        HmDatasourcePO po = hmDatasourceRepository.getById(id);
        HmDatasource datasource = BeanUtil.toBean(po, HmDatasource.class);

        List<HmDatasourceEnvPO> envPOS = hmDatasourceEnvRepository.findByDatasourceId(id);
        List<HmDatasourceEnv> envs = Convert.toList(HmDatasourceEnv.class, envPOS);
        datasource.setEnvList(envs);
        return datasource;
    }

    @Transactional(rollbackFor = Exception.class)
    public void save(HmDatasource hmDatasource, List<HmDatasourceEnv> envs) {
        validField(null, Fields.KEY, hmDatasource.getKey());
        HmDatasourcePO po = BeanUtil.toBean(hmDatasource, HmDatasourcePO.class);
        hmDatasourceRepository.save(po);
        for (HmDatasourceEnv env : envs) {
            HmDatasourceEnvPO envPO = BeanUtil.toBean(env, HmDatasourceEnvPO.class);
            envPO.setDatasourceId(po.getId());
            hmDatasourceEnvRepository.save(envPO);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void update(HmDatasource hmDatasource, List<HmDatasourceEnv> envs) {
        HmDatasourcePO po = hmDatasourceRepository.getById(hmDatasource.getId());
        po.setName(hmDatasource.getName());
        po.setRemark(po.getRemark());
        hmDatasourceRepository.updateById(po);
        hmDatasourceEnvRepository.deleteByDatasourceId(po.getId());
       List<HmDatasourceEnvPO> envPOS = Convert.toList(HmDatasourceEnvPO.class,envs);
       envPOS.forEach(e->e.setDatasourceId(po.getId()));
       hmDatasourceEnvRepository.saveBatch(envPOS);
    }

    public void remove(List<Long> ids) {
        for (Long id : ids) {
            hmDatasourceEnvRepository.deleteByDatasourceId(id);
            hmDatasourceRepository.removeById(id);
        }
    }

    public List<HmDatasource> getList() {
        List<HmDatasourcePO> pos = hmDatasourceRepository.list();
        return Convert.toList(HmDatasource.class, pos);
    }

    public PageBase<HmDatasource> getList(String key, String name, int pageNo, int pageSize) {
        Page<HmDatasourcePO> page = new Page<>(pageNo, pageSize);
        QueryWrapper<HmDatasourcePO> queryWrapper = new QueryWrapper<>();
        if (StringUtils.hasLength(key)) {
            queryWrapper.like(Fields.KEY_DB, EscapeUtil.escapeChar(key));
        }
        if (StringUtils.hasLength(name)) {
            queryWrapper.like(Fields.NAME, EscapeUtil.escapeChar(name));
        }
        queryWrapper.orderByDesc(DbConstants.CREATE_DATE);
        IPage<HmDatasourcePO> resultPage =
                hmDatasourceRepository.selectPage(queryWrapper, page);
        PageBase<HmDatasource> finalPage = PageBase.from(resultPage, HmDatasource.class);
        fillEnvList(finalPage.getData());
        return finalPage;
    }

    private void fillEnvList(List<HmDatasource> dsList) {
        if (dsList.isEmpty()) {
            return;
        }
        List<Long> idList = dsList.stream().map(HmDatasource::getId).collect(Collectors.toList());
        List<HmDatasourceEnvPO> envPOS = hmDatasourceEnvRepository.findByDatasourceIdIn(idList);
        for (HmDatasource datasource : dsList) {
            List<HmDatasourceEnvPO> pos = envPOS.stream().filter(e -> e.getDatasourceId().longValue() == datasource.getId().longValue()).collect(Collectors.toList());
            datasource.setEnvList(Convert.toList(HmDatasourceEnv.class, pos));
        }
    }


    public void validField(Long id, String field, String value) {


        if (Fields.KEY.equals(field)) {
            HmDatasourcePO po = hmDatasourceRepository.findByKey(value);
            if (po == null) {
                return;
            }
            if (id == null) {
                throw new ErrorKeyException(I18nKeyEnum.DATA_SOURCE_KEY_EXISTS);
            }
            if (po.getId().longValue() != id.longValue()) {
                throw new ErrorKeyException(I18nKeyEnum.DATA_SOURCE_KEY_EXISTS);
            }
        }
    }

    protected void fillEnvListByEnv(List<HmDatasource> dsList,String env){
        if (dsList.isEmpty()) {
            return;
        }
        List<Long> idList = dsList.stream().map(HmDatasource::getId).collect(Collectors.toList());
        QueryWrapper<HmDatasourceEnvPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("datasource_id" ,idList).eq("env_",env);

        List<HmDatasourceEnvPO> envPOS = hmDatasourceEnvRepository.list(queryWrapper);
        for (HmDatasource datasource : dsList) {
            List<HmDatasourceEnvPO> pos = envPOS.stream().filter(e -> e.getDatasourceId().longValue() == datasource.getId().longValue()).collect(Collectors.toList());
            datasource.setEnvList(Convert.toList(HmDatasourceEnv.class, pos));
        }
    }

}